/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.jm.financeiro.view;

import br.jm.financeiro.datamodel.LazyContaReceber;
import br.jm.financeiro.entity.ContaReceber;
import br.jm.financeiro.entity.ContaReceberParcela;
import br.jm.financeiro.filter.Funcoes;
import br.jm.financeiro.sistema.eao.ContaReceberEao;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.primefaces.context.RequestContext;
import org.primefaces.model.LazyDataModel;

/**
 *
 * @author joao
 */
public class ContaReceberBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private ContaReceber selectedContaReceber = new ContaReceber();
    private ContaReceberParcela selectContaReceberParcela;
    private final ContaReceberEao ContaReceberJpa;
    private LazyDataModel<ContaReceber> lazyModel;
    private List<ContaReceberParcela> lazyContaReceberParcela;
    private FacesMessage msg;
    private int numParcela = 1;
    private boolean parcela = true;
    private Date dataAtual = new Date();
    private Date dataVenc = new Date();
    private boolean salvar;
    private int rowid;

    public ContaReceberBean() {
        ContaReceberJpa = ContaReceberEao.getInstance();

        selectedContaReceber = new ContaReceber();
        selectContaReceberParcela = new ContaReceberParcela();
        lazyContaReceberParcela = new ArrayList<>();

        lazyModel = new LazyContaReceber(ContaReceberJpa);
    }

    public LazyDataModel<ContaReceber> getLazyModel() {
        return lazyModel;
    }

    public void setLazyModel(LazyDataModel<ContaReceber> lazyModel) {
        this.lazyModel = lazyModel;
    }

    public ContaReceber getSelectedContaReceber() {
        return selectedContaReceber;
    }

    public void setSelectedContaReceber(ContaReceber selectedContaReceber) {
        this.selectedContaReceber = selectedContaReceber;
    }

    public ContaReceberParcela getSelectContaReceberParcela() {
        if (selectContaReceberParcela == null) {
            selectContaReceberParcela = new ContaReceberParcela();
        }
        return selectContaReceberParcela;
    }

    public void setSelectContaReceberParcela(ContaReceberParcela selectContaReceberParcela) {
        this.selectContaReceberParcela = selectContaReceberParcela;
    }

    public List<ContaReceberParcela> getLazyContaReceberParcela() {
        return lazyContaReceberParcela;
    }

    public void setLazyContaReceberParcela(List<ContaReceberParcela> lazyContaReceberParcela) {
        this.lazyContaReceberParcela = lazyContaReceberParcela;
    }

    public void inserirReceber(ActionEvent event) {
        RequestContext context = RequestContext.getCurrentInstance();
        boolean loggedIn = false;

        try {
            if (ValidaReceber()) {
                this.selectedContaReceber.setIdReceber(null);

                ContaReceberJpa.create(this.selectedContaReceber);
                //eliminaParcelas();

                msg = new FacesMessage(FacesMessage.SEVERITY_INFO, LoginBean.AtualizaLog("", "Contas a Receber Inserido com Sucesso: ".concat(selectedContaReceber.getDscReceber())), selectedContaReceber.getDscReceber());
                loggedIn = true;
            }
        } catch (Exception e) {
            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro ao Inserir: " + selectedContaReceber.getDscReceber(), "");
        } finally {
            FacesContext.getCurrentInstance().addMessage(null, msg);
            context.addCallbackParam("loggedIn", loggedIn);
        }
    }

    public void alterarReceber(ActionEvent event) {
        RequestContext context = RequestContext.getCurrentInstance();
        boolean loggedIn = false;

        try {
            if (ValidaReceber()) {
                ContaReceberJpa.edit(selectedContaReceber);
                //eliminaParcelas();
                msg = new FacesMessage(FacesMessage.SEVERITY_INFO, LoginBean.AtualizaLog("", "Contas a Receber Alterado com Sucesso: ".concat(selectedContaReceber.getDscReceber())), selectedContaReceber.getDscReceber());
                loggedIn = true;
            }
        } catch (Exception e) {
            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro ao Alterar: " + selectedContaReceber.getDscReceber(), "");
        } finally {
            FacesContext.getCurrentInstance().addMessage(null, msg);
            context.addCallbackParam("loggedIn", loggedIn);
        }
    }

    public void excluirReceber(ActionEvent event) {
        try {
            ContaReceberJpa.destroy(selectedContaReceber);
            //eliminaParcelas();

            msg = new FacesMessage(FacesMessage.SEVERITY_INFO, LoginBean.AtualizaLog("", "Contas a Receber Excluido com Sucesso: ".concat(selectedContaReceber.getDscReceber())),selectedContaReceber.getDscReceber());
        } catch (Exception e) {
            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro ao Excluido: " + selectedContaReceber.getDscReceber(),
                    "");
        } finally {
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
    }

    public int getNumParcela() {
        return numParcela;
    }

    public void setNumParcela(int numParcela) {
        this.numParcela = numParcela;
    }

    public boolean isParcela() {
        return parcela;
    }

    public void setParcela(boolean parcela) {
        this.parcela = parcela;
    }

    public Date getDataAtual() {
        return dataAtual;
    }

    public void setDataAtual(Date dataAtual) {
        this.dataAtual = dataAtual;
    }

    public Date getDataVenc() {
        return dataVenc;
    }

    public void setDataVenc(Date dataVenc) {
        this.dataVenc = dataVenc;
    }

    public void recalculaParcela() {
        Calendar c = Calendar.getInstance();
        int nDias = 30;
        BigDecimal parcelas;
        BigDecimal nZero = new BigDecimal(0);
        BigDecimal nVlrDocumento = new BigDecimal(0);

        try {
            if (selectedContaReceber.getVlrReceber().floatValue() <= 0) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Obrigatório digitar Valor do Documento!", selectedContaReceber.getDscReceber()));
            } else {
                lazyContaReceberParcela = new ArrayList<ContaReceberParcela>();

                // Tira o Desconto
                nVlrDocumento = selectedContaReceber.getVlrReceber().subtract(selectedContaReceber.getVlrDesconto());
                parcelas = new BigDecimal(numParcela);
                // Divide e o coloca o resto na primeira parcela
                BigDecimal[] result = nVlrDocumento.divideAndRemainder(parcelas);

                for (int i = 0; i < numParcela; i++) {
                    selectContaReceberParcela = new ContaReceberParcela();

                    selectContaReceberParcela.setIdParcela(null);
                    selectContaReceberParcela.setNumParcela((i + 1));
                    selectContaReceberParcela.setDscParcela("Parcela " + (i + 1));
                    selectContaReceberParcela.setDatVcto(dataVenc);
                    selectContaReceberParcela.setTipStatus("A");
                    selectContaReceberParcela.setVlrDescontoParcela(nZero);
                    selectContaReceberParcela.setVlrJuros(nZero);
                    selectContaReceberParcela.setVlrMultaParcela(nZero);
                    selectContaReceberParcela.setVlrPago(nZero);
                    selectContaReceberParcela.setIdReceber(selectedContaReceber);
                    selectContaReceberParcela.setVlrImposto(nZero);

                    if (i == 0) {
                        selectContaReceberParcela.setVlrParcela(result[0].add(result[1]));
                    } else {
                        selectContaReceberParcela.setVlrParcela(result[0]);
                    }

                    c.add(Calendar.DATE, nDias);
                    dataVenc = c.getTime();

                    lazyContaReceberParcela.add(selectContaReceberParcela);
                }
                selectContaReceberParcela = new ContaReceberParcela();
                this.selectedContaReceber.setContaReceberParcelaList(lazyContaReceberParcela);
            }
        } catch (Exception ex) {
            FacesContext context = FacesContext.getCurrentInstance();
            String texto = "Erro no Processamento ...";
            msg = new FacesMessage(texto);
            msg.setSeverity(FacesMessage.SEVERITY_WARN);
            context.addMessage(null, msg);
        }
    }

    public void novoDocumento(ActionEvent event) {
        try {
            selectedContaReceber = new ContaReceber();
            selectContaReceberParcela = new ContaReceberParcela();
            lazyContaReceberParcela = new ArrayList<ContaReceberParcela>();
            lazyContaReceberParcela.add(selectContaReceberParcela);

            selectedContaReceber.setContaReceberParcelaList(lazyContaReceberParcela);
            selectedContaReceber.setDatEmissao(dataAtual);
            selectedContaReceber.setPerJuros(BigDecimal.ZERO);
            selectedContaReceber.setTipJuros("D");
            selectedContaReceber.setVlrDesconto(BigDecimal.ZERO);
            selectedContaReceber.setVlrMulta(BigDecimal.ZERO);
            selectedContaReceber.setVlrReceber(BigDecimal.ZERO);

            this.salvar = true;
        } catch (Exception ex) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Erro de Procesamento ...", selectedContaReceber.getDscReceber()));
        }
    }

    public void baixarParcela(ActionEvent event) {
        BigDecimal nPercJuros = selectedContaReceber.getPerJuros().divide(new BigDecimal("100"));
        BigDecimal nPercMulta = selectedContaReceber.getVlrMulta().divide(new BigDecimal("100"));

        BigDecimal nVlrParcela = selectContaReceberParcela.getVlrParcela();
        BigDecimal nVlrDesconto = selectContaReceberParcela.getVlrDescontoParcela();
        BigDecimal nVlrTotal = selectContaReceberParcela.getVlrPago();

        BigDecimal nVlrJuros = new BigDecimal(0);
        BigDecimal nVlrMulta = new BigDecimal(0);
        BigDecimal nVlrImposto = new BigDecimal(0);

        String cTipCalculo = selectedContaReceber.getTipJuros();
        int nDias = 0;

        try {
            if (selectContaReceberParcela.getDatVcto() == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Data Vencimento Inválida!", selectedContaReceber.getDscReceber()));
            } else if (selectContaReceberParcela.getDatPagto() == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Data Pagamento Inválida!", selectedContaReceber.getDscReceber()));
            } else if (nVlrParcela.compareTo(BigDecimal.ZERO) == 0) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Valor da Parcela Obrigatório!", selectedContaReceber.getDscReceber()));
            } else if (selectContaReceberParcela.getIdBaixa() == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Obrigatório selecionar Tipo de Baixa!", selectedContaReceber.getDscReceber()));
            } else if (selectContaReceberParcela.getIdPagamento() == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Obrigatório selecionar Tipo de Pagamento!", selectedContaReceber.getDscReceber()));
            } else {
                if (cTipCalculo.equals("D")) {
                    nDias = (int) Funcoes.diferencaEmDias(selectContaReceberParcela.getDatVcto(), selectContaReceberParcela.getDatPagto());
                } else {
                    nDias = Funcoes.diferencaEmMeses(selectContaReceberParcela.getDatVcto(), selectContaReceberParcela.getDatPagto());
                }

                if (nDias > 0) {
                    nVlrMulta = nVlrParcela.multiply(nPercMulta);
                    nVlrParcela = nVlrParcela.add(nVlrMulta);
                    nVlrJuros = nVlrParcela.multiply(nPercJuros).multiply(new BigDecimal(nDias));
                    nVlrTotal = nVlrJuros.add(nVlrParcela).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                } else {
                    nVlrTotal = nVlrParcela;
                }
                // APLICA O DESCONTO
                nVlrTotal = nVlrTotal.subtract(nVlrDesconto);
                
                // CALCULA VALOR DOS IMPOSTOS
                if (nVlrTotal.intValue() > selectContaReceberParcela.getVlrParcela().intValue()) {
                    nVlrImposto = nVlrTotal.subtract(selectContaReceberParcela.getVlrParcela());
                } else {
                    nVlrImposto = selectContaReceberParcela.getVlrParcela().subtract(nVlrTotal);
                }

                selectContaReceberParcela.setVlrMultaParcela(nVlrMulta);
                selectContaReceberParcela.setVlrJuros(nVlrJuros);
                selectContaReceberParcela.setVlrPago(nVlrTotal);
                selectContaReceberParcela.setTipStatus("P");
                selectContaReceberParcela.setVlrImposto(nVlrImposto);

                this.selectedContaReceber.getContaReceberParcelaList().set(this.rowid, selectContaReceberParcela);

                this.alterarReceber(event);

                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Baixa efetuada com sucesso!", selectedContaReceber.getDscReceber()));
            }
        } catch (Exception ex) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Erro de Procesamento ...", selectedContaReceber.getDscReceber()));
        }
    }

    public void baixarManualParcela(ActionEvent event) {
        BigDecimal nVlrJuros = selectContaReceberParcela.getVlrJuros();
        BigDecimal nVlrMulta = selectContaReceberParcela.getVlrMultaParcela();

        BigDecimal nVlrParcela = selectContaReceberParcela.getVlrParcela();
        BigDecimal nVlrDesconto = selectContaReceberParcela.getVlrDescontoParcela();
        BigDecimal nVlrTotal = selectContaReceberParcela.getVlrPago();
        BigDecimal nVlrImposto = new BigDecimal(0);

        try {
            if (selectContaReceberParcela.getDatVcto() == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Data Vencimento Inválida!", selectedContaReceber.getDscReceber()));
            } else if (selectContaReceberParcela.getDatPagto() == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Data Pagamento Inválida!", selectedContaReceber.getDscReceber()));
            } else if (nVlrParcela.compareTo(BigDecimal.ZERO) == 0) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Valor da Parcela Obrigatório!", selectedContaReceber.getDscReceber()));
            } else if (selectContaReceberParcela.getIdBaixa() == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Obrigatório selecionar Tipo de Baixa!", selectedContaReceber.getDscReceber()));
            } else if (selectContaReceberParcela.getIdPagamento() == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Obrigatório selecionar Tipo de Pagamento!", selectedContaReceber.getDscReceber()));
            } else {
                nVlrTotal = nVlrParcela.subtract(nVlrDesconto).add(nVlrMulta).add(nVlrJuros);

                // CALCULA VALOR DOS IMPOSTOS
                if (nVlrTotal.intValue() > selectContaReceberParcela.getVlrParcela().intValue()) {
                    nVlrImposto = nVlrTotal.subtract(selectContaReceberParcela.getVlrParcela());
                } else {
                    nVlrImposto = selectContaReceberParcela.getVlrParcela().subtract(nVlrTotal);
                }
                
                selectContaReceberParcela.setVlrMultaParcela(nVlrMulta);
                selectContaReceberParcela.setVlrJuros(nVlrJuros);
                selectContaReceberParcela.setVlrPago(nVlrTotal);
                selectContaReceberParcela.setTipStatus("P");
                selectContaReceberParcela.setVlrImposto(nVlrImposto);

                this.selectedContaReceber.getContaReceberParcelaList().set(this.rowid, selectContaReceberParcela);

                this.alterarReceber(event);

                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Baixa efetuada com sucesso!", selectedContaReceber.getDscReceber()));
            }
        } catch (Exception ex) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Erro de Procesamento ...", selectedContaReceber.getDscReceber()));
        }
    }

    public void gravarParcela(ActionEvent event) {
        try {
            if (selectContaReceberParcela.getDatPagto() != null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Data Pagamento preenchida - Utilize Baixa", selectedContaReceber.getDscReceber()));
            } else if (selectContaReceberParcela.getVlrPago().compareTo(BigDecimal.ZERO) > 0) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Valor Recebido preenchido - Utilize Baixa", selectedContaReceber.getDscReceber()));
            } else {
                this.selectedContaReceber.getContaReceberParcelaList().set(this.rowid, selectContaReceberParcela);

                this.alterarReceber(event);
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Gravação efetuada com sucesso!", selectedContaReceber.getDscReceber()));
            }
        } catch (Exception ex) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Erro de Procesamento ...", selectedContaReceber.getDscReceber()));
        }
    }

    public boolean isSalvar() {
        return salvar;
    }

    public void setSalvar(boolean salvar) {
        this.salvar = salvar;
    }

    public boolean ValidaReceber() {
        boolean lReturn = true;
        this.selectedContaReceber.setIdCusto(this.selectedContaReceber.getIdEmpreendimento().getIdCusto());

        if (this.selectedContaReceber.getDscReceber().isEmpty()) {
            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERRO - Descrição em Branco!", "");
            lReturn = false;
        } else if (this.selectedContaReceber.getIdCliente() == null) {
            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERRO - Obrigatório Definir o Fornecedor!", "");
            lReturn = false;
        } else if (this.selectedContaReceber.getIdCusto() == null) {
            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERRO - Obrigatório Definir o Centro de Custo!", "");
            lReturn = false;
        } else if (this.selectedContaReceber.getVlrReceber().floatValue() <= 0) {
            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERRO - Valor a Receber não Definido!", "");
            lReturn = false;
        } else if (this.selectedContaReceber.getContaReceberParcelaList().isEmpty()) {
            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERRO - Obrigatório Definir a Parcela!", "");
            lReturn = false;
        }
        return lReturn;
    }

    public void eliminaParcelas() {
        String cSql = "delete from conta_receber_parcela "
                + "where id_parcela not in (select id_parcela from conta_receber_conta_receber_parcela)";
        try {
            ContaReceberJpa.getNativeFiltro(cSql);
        } catch (Exception ex) {
            Logger.getLogger(ContaReceberBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int getRowid() {
        return rowid;
    }

    public void setRowid(int rowid) {
        this.rowid = rowid;
    }

}
